package org.jing.ext.compress.archieve;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
import org.apache.poi.ss.formula.functions.T;
import org.jing.core.lang.JingException;
import org.jing.core.logger.JingLogger;
import org.jing.core.util.FileUtil;
import org.jing.core.util.StringUtil;
import org.jing.ext.compress.BaseDecompress;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2023-02-23 <br>
 */
public class DecompressForZip extends BaseDecompress {
    private static final JingLogger LOGGER = JingLogger.getLogger(DecompressForZip.class);

    public DecompressForZip() {
        super();
    }

    public DecompressForZip(BaseDecompress decompress) {
        super(decompress);
    }

    @Override
    public List<File> decompress(File srcFile, String outputDirectory) {
        return null;
    }

    @Override
    public List<File> decompressMultiple(File[] srcFiles, String outputDirectory) {
        try {
            String outputPath = "temp/output/";
            FileUtil.deleteFile(outputPath);
            FileUtil.mkdirs(outputPath);
            ZipFile zipFile = new ZipFile("temp/temp.zip.001", "farmer".toCharArray());
            System.out.println(zipFile.isSplitArchive());
            zipFile.getFileHeaders().forEach(v -> {
                String fileName = getFileNameFromExtraData(v);
                LOGGER.debug("{} is {}", fileName, v.isDirectory() ? "directory" : "file");
                if (v.isDirectory()) {
                    FileUtil.mkdirs(outputPath + fileName);
                }
                else {
                    try (
                        InputStream inputStream = zipFile.getInputStream(v);
                        OutputStream outputStream = new FileOutputStream(new File(outputPath + fileName))
                    ) {
                        int index;
                        byte[] buffer = new byte[1024* 1024 * 10];
                        while (-1 != (index = inputStream.read(buffer))) {
                            outputStream.write(buffer, 0, index);
                        }
                        outputStream.flush();
                    }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
                        LOGGER.error(t);
                    }
                }
            });
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t);
        }
        return null;
    }
    public static String getFileNameFromExtraData(FileHeader fileHeader) {
        if(fileHeader.getExtraDataRecords()!=null){
            for (ExtraDataRecord extraDataRecord : fileHeader.getExtraDataRecords()) {
                long identifier = extraDataRecord.getHeader();
                if (identifier == 0x7075) {
                    byte[] bytes = extraDataRecord.getData();
                    ByteBuffer buffer = ByteBuffer.wrap(bytes);
                    byte version = buffer.get();
                    assert (version == 1);
                    int crc32 = buffer.getInt();
                    return new String(bytes, 5, buffer.remaining(), StandardCharsets.UTF_8);
                }
            }
        }
        return fileHeader.getFileName();
    }

    private void combineSplit(File[] files, File outputFile) {
        try (FileOutputStream writer = new FileOutputStream(outputFile)) {
            byte[] buffer = new byte[1024 * 1024];
            int index;
            for (File f$ : files) {
                try (FileInputStream reader = new FileInputStream(f$)) {
                    while (-1 != (index = reader.read(buffer))) {
                        writer.write(buffer, 0, index);
                    }
                    writer.flush();
                }
            }
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }

    /*private List<File> operate(ZipFile zipFile, String outputDirectory) throws Throwable {
        List<File> resultFiles = new ArrayList<>();
        if (!FileUtil.mkdirs(outputDirectory)) {
            throw new JingException("failed to make output directory: {}", outputDirectory);
        }
        ZipArchiveEntry entry;
        File subFile;
        Enumeration<ZipArchiveEntry> enumeration = zipFile.getEntries();
        InputStream reader;
        while (null != (entry = enumeration.nextElement())) {
            if (logFlag) {
                LOGGER.debug("decompressMultiple: {}", entry.getName());
            }
            if (entry.isDirectory()) {
                if (!FileUtil.mkdirs(subFile = new File(outputDirectory + File.separator + entry.getName()))) {
                    throw new JingException("failed to make sub directory: {}", outputDirectory + File.separator + entry.getName());
                }
                resultFiles.add(subFile);
            }
            else {
                reader = zipFile.getInputStream(entry);
                try (
                    FileOutputStream writer = new FileOutputStream(subFile = new File(outputDirectory + File.separator + entry.getName()))
                ) {
                    int len;
                    byte[] buffer = new byte[bufferSize];
                    while((len = reader.read(buffer)) != -1){
                        writer.write(buffer, 0, len);
                    }
                    writer.flush();
                    resultFiles.add(subFile);
                }
            }
        }
        return resultFiles;
    }*/
}
